# -*- conding:utf-8 -*-
from algorithm.MGraph import MDWGraph
import numpy as np
import random

inf = 999999

global graphinfos


class randomGR(object):
    # 随机生成图：随机生成M个结点，连边概率p条边的图，为保证网络质量，每个结点至少有一条边与其他结点相连
    def random_initial_Graph(self, N, function_V_num, p, max_E_cost) -> object:
        V = list(range(N))
        while True:
            E = np.zeros((N, N))
            for i in range(len(E)):
                for j in range(len(E)):
                    if i != j and E[i][j] == 0:
                        E[i][j] = E[j][i] = inf
            # 随机产生边
            for i in range(N):
                flag = 0
                for j in range(N):
                    if j == i:
                        continue
                    prob = random.random()
                    if prob < p:
                        flag = 1
                        Eij_cost = random.randint(1, max_E_cost)  # 随机产生边权
                        E[i][j] = E[j][i] = Eij_cost
                if flag == 0:
                    j = random.randint(0, N - 1)  # 随机产生相连结点
                    if i != j:
                        Eij_cost = random.randint(1, max_E_cost)  # 随机产生边权
                        E[i][j] = E[j][i] = Eij_cost
            initial_Graph = MDWGraph(V, E)
            dist = initial_Graph.floyd_warshall(1)
            if inf not in dist[0]:
                break

        # 随机产生功能结点
        function_V = []
        while True:
            if len(function_V) < function_V_num:
                F_V = random.randint(0, N - 1)
                if F_V not in function_V:
                    function_V.append(F_V)
            else:
                break

        # 随机产生的边资源限制
        E_constrains = np.zeros((N, N))
        for i in range(len(E)):
            for j in range(i + 1, len(E)):
                if E[i][j] != 999 and i != j:
                    # E_constrains[i][j] = E_constrains[j][i] = random.randint(1000, 10000)
                    E_constrains[i][j] = E_constrains[j][i] = random.randint(1000, 10000)

        # 随机产生功能结点限制
        function_V_constrains = []
        for i in range(function_V_num):
            # function_V_constrains.append(random.randint(4000, 12000))
            function_V_constrains.append(random.randint(4000, 12000))
        neibor_function_v = []
        neibor_function_v.append(function_V[random.randint(0, len(function_V) - 1)])
        v = function_V[random.randint(0, len(function_V) - 1)]
        while v in neibor_function_v:
            v = function_V[random.randint(0, len(function_V) - 1)]
        neibor_function_v.append(v)
        v1 = neibor_function_v[0]
        v2 = neibor_function_v[1]

        for i in range(initial_Graph.vnum):
            if initial_Graph.E[i][v1] != 0 and initial_Graph.E[i][v1] != inf:
                initial_Graph.E[i][v1] = initial_Graph.E[v1][i] = 100

        return initial_Graph, function_V, E_constrains, function_V_constrains, neibor_function_v

    # 随机产生请求request
    def random_request(self, N, function_num, function_V_num, max_bk, max_deployment_cost,
                       parallel_num, function_V, destination_V_radio, neibor_function_v, initial_Graph,
                       parallel_position) -> object:
        request = {}
        while True:
            source = random.randint(0, N - 1)
            if source not in function_V:
                request['source'] = source
                break

        SFC = []
        for i in range(function_num):
            SFC.append(i)
        request['SFC'] = SFC
        destination = []

        destination_num = int(destination_V_radio * N)
        if destination_num <= 3:
            destination_num = 3
        while len(destination) < destination_num:
            d = random.randint(0, N - 1)
            if d not in function_V and d not in destination and d != source:
                destination.append(d)
        request['destination'] = destination
        bk = random.randint(2, max_bk)

        request['bk'] = bk

        deployment_cost = np.zeros((function_V_num, function_num))
        v1 = function_V.index(neibor_function_v[0])

        start = max(parallel_position - 1, 0)
        end = min(parallel_num + parallel_position + 1, function_num - 1)
        f1 = random.randint(start, end)
        f2 = random.randint(start, end)
        while f1 == f2:
            f2 = random.randint(start, end)
        for i in range(function_num):
            deployment_cost[v1][i] = 699
            # deployment_cost[v2][i] = 699
        for i in range(len(function_V)):
            deployment_cost[i][f1] = 699
            deployment_cost[i][f2] = 699
        deployment_cost[v1][f1] = random.randint(1, max_deployment_cost)
        deployment_cost[v1][f2] = random.randint(1, max_deployment_cost)

        for i in range(function_num):
            if i == f1 or i == f2:
                continue
            v = random.randint(0, len(function_V) - 1)
            while v == v1:
                v = random.randint(0, len(function_V) - 1)
            deployment_cost[v][i] = random.randint(1, max_deployment_cost)

        for i in range(function_V_num):
            for j in range(function_num):
                if deployment_cost[i][j] == 0 and function_num != f1 and function_num != f2:
                    # flag = random.randint(0, 1)
                    deploy_pro = random.random()
                    # print(deploy_pro)
                    if deploy_pro < 0.3:
                        deployment_cost[i][j] = 699
                    else:
                        deployment_cost[i][j] = (random.randint(1, max_deployment_cost))

        request['deployment_cost'] = deployment_cost
        request['parallel_num'] = parallel_num
        request['parallel_position'] = 0
        request['function_num'] = 5

        print('随机产生的请求为：', request)
        return request
